package tool

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"sort"
	"strconv"
	"strings"
	"time"
)

const (
	Layout          = "2006-01-02 15:04:05"
	DateTime        = "2006-01-02"
	DefaultExecTime = "0_0_0"
)

// StringToTimeUnix 时间字符串转换成时间戳
// a.g 6_2_3  ===> 转换成 6天2小时3分钟后的时间戳
// TODO 需要优化代码写得太死，需要优化后兼容秒的场景
func StringToTimeUnix(execTimeStr string) int64 {
	var processAt = time.Now().Unix()
	if execTimeStr == DefaultExecTime {
		return processAt
	}

	execTime := strings.Split(execTimeStr, "_")
	if len(execTime) < 3 {
		return processAt
	}

	// 天数
	days, _ := strconv.Atoi(execTime[0])
	processAt += int64(days) * 24 * 60 * 60
	// 小时
	hours, _ := strconv.Atoi(execTime[1])
	processAt += int64(hours) * 60 * 60

	// 分钟
	minutes, _ := strconv.Atoi(execTime[2])
	processAt += int64(minutes) * 60

	return processAt
}

func GetLocalTime(timeStr string) time.Time {
	execTime, _ := time.ParseInLocation(Layout, timeStr, time.Local)
	return execTime
}

// TimeParseLocalUnix 获取当天零点的时间戳
// eg 2023-02-22 => 1676995200
func TimeParseLocalUnix(DayTime string) int64 {
	value := DayTime
	if len(DayTime) <= 11 {
		value = fmt.Sprintf("%s 00:00:00", DayTime)
	}

	loc, _ := time.LoadLocation("Local")
	theTime, _ := time.ParseInLocation(Layout, value, loc)
	return theTime.Unix()
}

func Md5String(input string) string {
	s := md5.New()
	digest := strings.ReplaceAll(input, "\n", "")
	s.Write([]byte(digest))
	return hex.EncodeToString(s.Sum(nil))
}

// TimeBetween 获取指定时间范围内天数
// eg startTime => "2023-06-01" endTime => "2023-06-03"
// return ["2023-06-01","2023-06-02","2023-06-03"]
func TimeBetween(startTime, endTime string) []string {
	startDate, _ := time.ParseInLocation("2006-01-02", startTime, time.Local)
	endDate, _ := time.ParseInLocation("2006-01-02", endTime, time.Local)
	timeList := make([]string, 0)
	for endDate.After(startDate) {
		timeList = append(timeList, startDate.Format("2006-01-02"))
		startDate = startDate.AddDate(0, 0, 1)
	}
	timeList = append(timeList, endTime)
	return timeList
}

// Median 获取切片的中位值
func Median(nums []float64) float64 {
	sort.Float64s(nums)
	n := len(nums)
	if n%2 == 0 {
		return (nums[n/2-1] + nums[n/2]) / float64(2)
	} else {
		return nums[n/2]
	}
}

// MedianInt64 获取切片的中位值
func MedianInt64(nums []int64) int64 {
	sort.Slice(nums, func(i, j int) bool {
		return nums[i] < nums[j]
	})
	n := len(nums)
	if n%2 == 0 {
		return (nums[n/2-1] + nums[n/2]) / 2
	} else {
		return nums[n/2]
	}
}

// TimeSub 计算两个时间的差值
// eg startTime => "2022-05-01 09:07:08"
// eg endTime => "00:06:35"
// eg return =>  2022-05-01 09:00:33
func TimeSub(startTime, endTime string) string {
	str := strings.Split(endTime, ":")
	if len(str) < 3 {
		return ""
	}
	durationStr := fmt.Sprintf("%sh%sm%ss", str[0], str[1], str[2])

	timeValue, err := time.Parse(time.RFC3339, startTime)
	if err != nil {
		fmt.Println("解析时间出错:", err)
		return ""
	}

	// 解析持续时间字符串为 time.Duration 类型
	durationValue, err := time.ParseDuration(durationStr)
	if err != nil {
		fmt.Println("解析持续时间出错:", err)
		return ""
	}

	// 计算时间之间的差异
	return timeValue.Add(-durationValue).Format(Layout)
}

// Decimal 对float64类型数据四舍五入，并保留2位有效销售
func Decimal(value float64) float64 {
	value, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", value), 64)
	return value
}
